const crypto = require('crypto');
const querystring = require('querystring');
const axios = require('axios'); // 使用axios进行HTTP请求
const moment = require('moment-timezone'); // 使用moment-timezone处理时间
const { v4: uuidv4 } = require('uuid'); //uuidv4生成唯一标识符
const Buffer = require('buffer').Buffer; // 使用Buffer处理二进制数据
const https = require('https');

// 设置时区
moment.tz.setDefault('Asia/Shanghai');

class Credential {
    constructor(AK, SK) {
        this.AK = AK;
        this.SK = SK;
    }

    async doCTAPIRequest(request) {
        let reqURL = request.url;
        const {url, method, headers, data, query} = request;
        let queryStr = this.getCTAPISortedQueryString(query);
        if (queryStr !== '') {
            reqURL += `?${queryStr}`;
        }

        let reqBody = '';
        if (data) {
            if (headers['Content-Type'] === 'application/json') {
                reqBody = JSON.stringify(data);
                headers['Content-Type'] = 'application/json; charset=utf-8';
            } else {
                reqBody = querystring.stringify(data);
                headers['Content-Type'] = 'application/x-www-form-urlencoded';
            }
        }

        delete headers['regionId'];
        const uuid = this.generateUUID();
        const eopDate = moment().tz("Asia/Shanghai").format('YYYYMMDDTHHmmss') + 'Z';
        const authorization = this.getCTAPIAuthorization(queryStr, reqBody, uuid, this.AK, this.SK, eopDate);

        const config = {
            headers: {
                ...headers, //headers传入regionID/content-type，补充认证信息
                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/110.0',
                'Ctyun-Eop-Request-Id': uuid,
                'Eop-Date': eopDate,
                'Eop-Authorization': authorization,
            },
            // httpsAgent: new (require('https').Agent)({ rejectUnauthorized: false }),
        };

        //避免axios的https证书验证问题，使用node原生https请求
        return new Promise((resolve, reject) => {
            const options = {
              hostname: request.endpoint,
              port: 443,
              path: reqURL,
              method: method,
              headers: {
                ...config.headers,
                'Content-Type': 'application/json',
                'Content-Length': Buffer.byteLength(reqBody)
              },
              // 添加agent配置，禁用证书验证
              agent: new https.Agent({
                rejectUnauthorized: false
              })
            };
        
            let req = https.request(options, (res) => {
              console.log( `statusCode: ${res.statusCode}`);
              
              // 处理响应头
              res.on('headers', (headers, statusLine, requestInfo) => {
                console.log(`headers: ${headers})`);
              });

              let responseData = '';
              // 处理响应数据
              res.on('data', (chunk) => {
                console.log(`Received chunk: ${chunk}`); // JSON字符串响应
                responseData += chunk;

              });
        
              res.on('end', () => {
                console.log('Receive end.'); // 解析成功的结果
                try {
                  const jsonRes = JSON.parse(responseData);
                  resolve(jsonRes);
                } catch (error) {
                  console.error('JSON parse error: ', error);
                  reject(error); // 拒绝错误
                }
              });
            });
        
            req.on('error', (error) => {
              console.error('CTAPIdoRequest error: ', error);
              reject(error); // 拒绝错误
            });
        
            // 写入请求体
            req.write(reqBody);
            req.end();
          });
    }

    generateUUID() {
        return uuidv4();
    }

    getCTAPISortedQueryString(query) {
        const queryArray = Object.entries(query).map(([key, value]) => `${key}=${value}`);
        queryArray.join('&'); //构建URL查询字符串格式
        // return querystring.stringify(queryArray.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}));
        return queryArray;
    }

    getCTAPIAuthorization(query, body, uuid, ak, sk, timestamp) {
        const hashedRequestBody = crypto.createHash('sha256').update(body).digest('hex');
        let signature = `ctyun-eop-request-id:${uuid}\neop-date:${timestamp}\n\n${query}\n${hashedRequestBody}`;
        const ktime = this.signatureMethod(sk, timestamp, 'sha256');
        const kak = this.signatureMethod(ktime, ak, 'sha256');
        //应当使用timeStamp的截短，而非完整的timestamp
        const kdate = this.signatureMethod(kak, timestamp.slice(0,8), 'sha256');
        const signaSha256 = this.signatureMethod(kdate, signature, 'sha256'); 
        // 仅对signaSha256进行一次base64编码
        const base64Signa = Buffer.from(signaSha256).toString('base64');
        const signHeader = `${ak} Headers=ctyun-eop-request-id;eop-date Signature=${base64Signa}`;
        return signHeader;
    }

    signatureMethod(key, message, algorithm) {
        const hmac = crypto.createHmac(algorithm, key);
        hmac.update(message);
        return hmac.digest(); //不进行base64编码
    }
}

module.exports = Credential;